package com.netposa.datawarehouse.aggregator.client.search;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.netposa.appwebres.common.WebResInfo;
import com.netposa.datawarehouse.aggregator.client.BodyServiceClient;
import com.netposa.datawarehouse.aggregator.client.FaceServiceClient;
import com.netposa.datawarehouse.aggregator.client.fallback.BaseServiceClientFallback;
import com.netposa.datawarehouse.aggregator.search.ResourceParam;
import com.netposa.datawarehouse.aggregator.search.ResourceResult;
import com.netposa.datawarehouse.aggregator.web.model.DefaultCondition;
import com.netposa.library.datawarehouse.aggregate.helper.ResourceDefined.ResourceInnerFiled;
import com.netposa.library.datawarehouse.aggregate.helper.ResourceDefined.ResourceType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

@Component("face")
public class FaceResourceSearch extends AbstractResourceSearch {
   private final Logger logger = LoggerFactory.getLogger(FaceResourceSearch.class);
   @Autowired
   private FaceServiceClient faceServiceClient;
   @Autowired
   private BodyServiceClient bodyServiceClient;
   @Autowired
   private BaseServiceClientFallback serviceClientFallback;
   @Autowired
   private Gson gson;

   public List<ResourceResult> search(List<ResourceParam> resourceParams) {
      if (resourceParams != null && !resourceParams.isEmpty()) {
         String recordIds = Joiner.on(",").skipNulls().join(Lists.transform(resourceParams, (input) -> {
            return input == null ? null : input.getRecordId();
         }));
         FaceServiceClient.FaceCondition condition = new FaceServiceClient.FaceCondition();
         condition.setRecordIds(recordIds);
         WebResInfo webResInfo = this.faceServiceClient.getFaceOriginalByIds(condition);
         List<ResourceResult> resourceResults = new ArrayList<>();
         if (webResInfo.getCode().equalsIgnoreCase("200") && webResInfo.getData() != null) {
            String dataJson = this.gson.toJson(webResInfo.getData());
            List list = this.gson.fromJson(dataJson, (new TypeToken<List<Map<String, Object>>>() {
            }).getType());
            resourceResults = Lists.transform(list, new Function<Map<String, Object>,ResourceResult>() {
               public ResourceResult apply(Map input) {
                  ResourceResult result = new ResourceResult();
                  result.setData(input);
                  result.getData().put(ResourceInnerFiled._TYPE.getFiled(), ResourceType.FACE.getValue());
                  Map map = new HashMap();
                  result.getData().put(ResourceInnerFiled.RELATION_RECORD.getFiled(), FaceResourceSearch.this.gson.toJson(map));
                  result.getData().put(ResourceInnerFiled._RECORD_ID.getFiled(), input.get("recordId"));
                  result.getData().put(ResourceInnerFiled._ABS_TIME.getFiled(), input.get("absTime"));
                  result.getData().put(ResourceInnerFiled.SOURCE.getFiled(), result.getData().get("source"));
                  return result;
               }

               private Object getBodyData(Map input) {
                  Object recordId = input.get("recordId");
                  String collectionId = "";
                  if (recordId != null) {
                     collectionId = String.valueOf(recordId);
                  }

                  BodyServiceClient.BodyCondition bodyCondition = new BodyServiceClient.BodyCondition();
                  bodyCondition.setRecordIds(collectionId);
                  WebResInfo faceData = FaceResourceSearch.this.bodyServiceClient.getBodyOriginalByIds(bodyCondition);
                  List dataList = (List)faceData.getData();
                  return dataList != null && dataList.size() > 0 ? dataList.get(0) : null;
               }
            });
         } else {
            this.logger.error("Request face server failed {} = {} .", webResInfo.getCode(), webResInfo.getMessage());
         }

         return (List)resourceResults;
      } else {
         return new ArrayList();
      }
   }

   public List selectInParams(DefaultCondition defaultCondition) {
      WebResInfo webResInfo = this.faceServiceClient.getFaceOriginalList(JSON.toJSONString(defaultCondition));
      return this.rebuild(webResInfo, ResourceType.FACE.getValue());
   }

   public List<ResourceResult> selectInParams2(RequestMethod requestMethod, String serviceName, String typeName, String path, String requestBody) {
      WebResInfo webResInfo = this.serviceClientFallback.handler(requestMethod, serviceName, path, requestBody);
      return this.rebuild(webResInfo, typeName);
   }

   public Integer count(DefaultCondition defaultCondition) {
      WebResInfo webResInfo = this.faceServiceClient.countFace(JSON.toJSONString(defaultCondition));
      if (webResInfo.getCode().equalsIgnoreCase("200") && webResInfo.getData() != null) {
         Double count = Double.valueOf(String.valueOf(webResInfo.getData()));
         return count.intValue();
      } else {
         this.logger.error("Request face server failed {} = {} .", webResInfo.getCode(), webResInfo.getMessage());
         return 0;
      }
   }

   public List rebuild(WebResInfo webResInfo, String type) {
      if (webResInfo.getCode().equalsIgnoreCase("200") && webResInfo.getData() != null) {
         Map resultData = (Map)webResInfo.getData();
         List<Map<String,Object>> list = (List)resultData.get("list");
         return Lists.transform(list, (input) -> {
            ResourceResult result = new ResourceResult();
            result.setData(input);
            result.getData().put(ResourceInnerFiled._TYPE.getFiled(), ResourceType.FACE.getValue());
            result.getData().put(ResourceInnerFiled._RECORD_ID.getFiled(), input.get("recordId"));
            result.getData().put(ResourceInnerFiled._ABS_TIME.getFiled(), input.get("absTime"));
            result.getData().put(ResourceInnerFiled.SOURCE.getFiled(), result.getData().get("source"));
            result.addRequestId(ResourceType.FACE.getValue(), Objects.toString(resultData.get("requestId")));
            return result;
         });
      } else {
         this.logger.error("Request face server failed {} = {} .", webResInfo.getCode(), webResInfo.getMessage());
         return Lists.newArrayList();
      }
   }
}
